#ifndef VIDEO_INPUT_H_
#define VIDEO_INPUT_H_

#include "DefaultDefine.h"

namespace hiych {

//vi类
class VideoInput
{
public:
    using DATA_VI_TYPE = SAMPLE_VI_CONFIG_S;

    using DATA_DEV = SAMPLE_DEV_INFO_S;
    using DATA_SNS = SAMPLE_SENSOR_INFO_S;
    using DATA_PIPE = SAMPLE_PIPE_INFO_S;
    using DATA_CHN = SAMPLE_CHN_INFO_S;
    using DATA_SNAP = SAMPLE_SNAP_INFO_S;

    #define DEV_CONFIG 0
    #define PIPE_FLAG 1
    #define CHANNEL_FLAG 2
private:
    DATA_VI_TYPE* viParam;

    bool configFlag[3]{0};

    void initViParam();
public:
    void setDev(const VI_DEV& devId = 0,const WDR_MODE_E& wdrMode = WDR_MODE_NONE);

    void setPipe(
        const VI_PIPE& pipe0,const VI_PIPE& pipe1, const VI_PIPE& pipe2,const VI_PIPE& pipe3,
        const VI_VPSS_MODE_E& mode = VI_OFFLINE_VPSS_OFFLINE
    );

    void setChannel(
        const VI_CHN& channelId,    
        const PIXEL_FORMAT_E& pixFormat = PIXEL_FORMAT_YVU_SEMIPLANAR_420,
        const VIDEO_FORMAT_E& videoFormat = VIDEO_FORMAT_LINEAR, 
        const DYNAMIC_RANGE_E& dynamicRange = DYNAMIC_RANGE_SDR8, 
        const COMPRESS_MODE_E& compressMode = COMPRESS_MODE_SEG
    );

    bool isConfigSetComplete() const;

    DATA_VI_TYPE* getParam() const;
public:
    VideoInput();
    ~VideoInput();
};

VideoInput::VideoInput():
    viParam(nullptr)
{
    try
    {
        this->viParam = new DATA_VI_TYPE;
    }
    catch(const std::bad_alloc& e)
    {
        std::cerr << e.what() << '\n';
    }

    memset_s(this->viParam, sizeof(DATA_VI_TYPE), 0, sizeof(DATA_VI_TYPE));

    initViParam();
}

VideoInput::~VideoInput()
{
    delete viParam;
}

void VideoInput::initViParam()
{
    SAMPLE_COMM_VI_GetSensorInfo(this->viParam);
    
    this->viParam->as32WorkingViId[0] = 0;
    this->viParam->s32WorkingViNum = 1;

    this->viParam->astViInfo[0].stSnsInfo.MipiDev = SAMPLE_COMM_VI_GetComboDevBySensor(
        this->viParam->astViInfo[0].stSnsInfo.enSnsType,
        0
    );

    this->viParam->astViInfo[0].stSnsInfo.s32BusId = 0;
}

void VideoInput::setDev(const VI_DEV& devId,const WDR_MODE_E& wdrMode)
{
    DATA_DEV *dev = &(this->viParam->astViInfo[0].stDevInfo);

    dev->enWDRMode = wdrMode;
    dev->ViDev = devId;

    configFlag[DEV_CONFIG] = true;
}

void VideoInput::setPipe(
        const VI_PIPE& pipe0,const VI_PIPE& pipe1, const VI_PIPE& pipe2,const VI_PIPE& pipe3,
        const VI_VPSS_MODE_E& mode
    )
{
    DATA_PIPE *pipe = &(this->viParam->astViInfo[0].stPipeInfo);
    pipe->aPipe[0] = pipe0;
    pipe->aPipe[1] = pipe1;
    pipe->aPipe[2] = pipe2;
    pipe->aPipe[3] = pipe3;

    pipe->enMastPipeMode= mode;

    configFlag[PIPE_FLAG] = true;
}

void VideoInput::setChannel(
        const VI_CHN& channelId,    
        const PIXEL_FORMAT_E& pixelFormat,
        const VIDEO_FORMAT_E& videoFormat, 
        const DYNAMIC_RANGE_E& dynamicRange, 
        const COMPRESS_MODE_E& compressMode
    )
{
    DATA_CHN *channel = &(this->viParam->astViInfo[0].stChnInfo);

    channel->ViChn = channelId;
    channel->enPixFormat = pixelFormat;
    channel->enVideoFormat = videoFormat;
    channel->enDynamicRange = dynamicRange;
    channel->enCompressMode = compressMode;

    configFlag[CHANNEL_FLAG] = true;
}

VideoInput::DATA_VI_TYPE* VideoInput::getParam() const
{
    return this->viParam;
}

bool VideoInput::isConfigSetComplete() const
{
    for(auto i:configFlag)
        if(configFlag[i] == false)
            return false;
 
    return true;
}

}

#endif